package com.yth.utils;

import java.util.Collections;
import java.util.Map;

/**
 * @author yutianhong
 * @version 1.0
 * @since 2025/3/14 12:47
 */
public class SimpleMapUtils {

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    private static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * 计算HashMap存放指定数量元素时的最优初始容量，避免扩容
     *
     * @param expectedSize 预期存放的键值对数量
     * @return 初始容量值（保证为2的幂次方，不超过MAXIMUM_CAPACITY）
     * <p>
     * 计算公式：
     * 1. 容量基数 = expectedSize / 负载因子 + 1
     * 2. 结果调整为不小于基数的最小2的幂次方
     */
    public static int calculateInitialCapacity(int expectedSize) {
        if (expectedSize < 0) {
            throw new IllegalArgumentException("Expected size must be non-negative");
        }
        if (expectedSize == 0) {
            return 2;
        }
        float ft = ((float) expectedSize / DEFAULT_LOAD_FACTOR) + 1.0F;
        int t = ((ft < (float) MAXIMUM_CAPACITY) ?
                (int) ft : MAXIMUM_CAPACITY);
        return tableSizeFor(t);
    }

    public static <K, V> Map<K, V> orEmptyMap(Map<K, V> map) {
        return map == null ? Collections.emptyMap() : map;
    }

    /**
     * Returns a power of two size for the given target capacity.
     */
    private static int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

    private SimpleMapUtils() {
    }
}
